package com.meis.widget;


import com.meis.widget.utils.AttrUtils;
import cs.help.tool.Log;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.Image;
import ohos.agp.components.ListContainer;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.Path;
import ohos.agp.render.PixelMapHolder;
import ohos.agp.utils.Color;
import ohos.agp.utils.Matrix;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Rect;
import ohos.media.image.common.Size;

/**
 * desc:滚动视差控件
 * author: wens
 * date: 2018/1/21.
 */

public class MeiScrollParallaxView extends Image implements Component.BindStateChangedListener,
        Component.DrawTask, Component.EstimateSizeListener, Component.LayoutRefreshedListener, Component.ScrolledListener {

    //圆角外的颜色 手动设置跟图片背景色一致
    private int mOutRoundColor = Color.WHITE.getValue();

    //是否绘制圆形  若为 true 圆角失效
    private boolean mIsCircle;

    //是否显示视差
    private boolean mIsParallax;

    //实际图形矩形
    // private RectFloat mRect;

    //用于绘制圆角路径
    private Path mPath;

    //圆角画笔
    private Paint mPaint;

    //矩阵
    private Matrix mMatrix;

    //屏幕中的位置
    private int[] mScreenLocation = new int[2];

    //圆角半径
    private int mRoundWidth;

    //默认的视差滚动速率 (0~1)
    private float mParallaxRate;
    private static final float DEFAULT_PARALLAX_RATE = 0.3F;

    //屏幕高度
//    private int mScreenHeight = 0;
    private PixelMap pixelMap;
    float parallaxScale = 0;

    //private float[] mCorners;

    public MeiScrollParallaxView(Context context) {
        this(context, null);
    }

    public MeiScrollParallaxView(Context context, AttrSet attrs) {
        this(context, attrs, "");
    }

    public MeiScrollParallaxView(Context context, AttrSet attrs, String defStyleAttr) {
        super(context, attrs, defStyleAttr);
        if (attrs != null) {
            mParallaxRate = AttrUtils.getFloatFromAttr(attrs, "parallaxRate", DEFAULT_PARALLAX_RATE);
            mIsParallax = AttrUtils.getBooleanFromAttr(attrs, "enableParallax", true);
            mIsCircle = AttrUtils.getBooleanFromAttr(attrs, "enableCircle", false);
            mRoundWidth = AttrUtils.getIntegerFromAttr(attrs, "roundWidth", 0);
            mOutRoundColor = AttrUtils.getColorFromAttr(attrs, "outRoundColor", Color.WHITE.getValue());
        }
        init();

        setEstimateSizeListener(this::onEstimateSize);
        addDrawTask(this::onDraw);
        setLayoutRefreshedListener(this);
        setBindStateChangedListener(this);

    }

    private void setmOutRound() {
    }

    private void init() {
        mMatrix = new Matrix();

        mPath = new Path();
        mPath.setFillType(Path.FillType.INVERSE_EVEN_ODD);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(new Color(mOutRoundColor));

//        mScreenHeight = DensityUtil.getScreenHeight(getContext());
    }


    @Override
    public boolean onEstimateSize(int i, int i1) {
        Log.i("MeiScrollParallaxView", "-----------------------onEstimateSize()");
        if (mIsCircle) {
            int width = getEstimatedWidth();
            int height = getEstimatedHeight();
//            setMeasuredDimension(Math.min(width, height), Math.min(width, height));
            setEstimatedSize(Math.min(width, height), Math.min(width, height));
            return true;
        }
        return false;
    }

    @Override
    public void onRefreshed(Component component) {
        Log.i("MeiScrollParallaxView", "-----------------------onRefreshed()");
        mPath.reset();
        int w = component.getWidth();
        int h = component.getHeight();
        if (mRoundWidth != 0) {
            //获取圆角大小
            mRoundWidth = mIsCircle ? Math.min(w / 2, h / 2) : mRoundWidth;
            //添加圆角矩形
            mPath.addRoundRect(new RectFloat(0, 0, w, h), mRoundWidth, mRoundWidth, Path.Direction.COUNTER_CLOCK_WISE);
        }
        invalidate();
    }


//    private int top = 0;

    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (getPixelMap() == null) {
            return;
        }
        if (mIsParallax) {
            setPixelMap(null);
            int[] locationOnScreen = getLocationOnScreen();
            mScreenLocation[0] = locationOnScreen[0];
            mScreenLocation[1] = locationOnScreen[1];
            float[] data = getDrawPixelmapInfo();
            Rect rect = new Rect(((int) data[0]), ((int) data[1]), ((int) data[2]), ((int) data[3]));
            PixelMap.InitializationOptions initializationOptions = new PixelMap.InitializationOptions();
            initializationOptions.size = new Size((int) data[4], (int) (data[5]));
            initializationOptions.pixelFormat = PixelFormat.ARGB_8888;
            PixelMap showPixmap = PixelMap.create(getPixelMap(), rect, initializationOptions);
            canvas.drawPixelMapHolder(new PixelMapHolder(showPixmap), data[6], data[7], mPaint);
            canvas.restore();
        }
        canvas.drawPath(mPath, mPaint);
    }

    /**
     * 设置滑动速率
     *
     * @param rate 滑动速率
     * @return MeiScrollParallaxView
     */
    public MeiScrollParallaxView setParallaxRate(int rate) {
        if (rate < 0) {
            rate = 0;
        }
        this.mParallaxRate = rate;
        return this;
    }

    /**
     * 是否显示视差
     *
     * @param parallax 是否显示视差
     * @return MeiScrollParallaxView
     */
    public MeiScrollParallaxView setParallax(boolean parallax) {
        mIsParallax = parallax;
        return this;
    }


    @Override
    public void onComponentBoundToWindow(Component component) {
        if (listContainer == null) {
            getRootListContainer();
        }
        listContainer.addScrolledListener(this);
    }

    @Override
    public void onComponentUnboundFromWindow(Component component) {
        if (listContainer == null) {
            getRootListContainer();
        }
        listContainer.removeScrolledListener(this);
    }


    private ListContainer listContainer;

    public void setListContainer(ListContainer listContainer) {
        this.listContainer = listContainer;
    }

    public ListContainer getRootListContainer() {
        return listContainer;
    }

    @Override
    public void onContentScrolled(Component component, int i, int i1, int i2, int i3) {
        Log.i("MeiScrollParallaxView", "--------------onContentScrolled   " + i3 + "   " + i1);
        if (parallaxScale != 0) {
            mMatrix.postTranslate(i - i2, (i1 - i3) / parallaxScale);
        } else {
            mMatrix.postTranslate(i - i2, (i1 - i3));
        }
        invalidate();
    }

    @Override
    public void scrolledStageUpdate(Component component, int newStage) {
        Log.i("MeiScrollParallaxView", "--------------scrolledStageUpdate");
    }

    // 获取图片矩阵区域
    private float[] getDrawPixelmapInfo() {
        PixelMap pixelMap = getPixelMap();
        Size pixelMapSize = pixelMap.getImageInfo().size;
        //视图高度
        // float vh = getHeight();
//        float vw = getWidth();
        //最大滑动高度
//        float ph = (1 + mParallaxRate) * vh;
        float scaleX = getHeight() / (float) pixelMapSize.height;
        float scaleY = getWidth() / (float) pixelMapSize.width;
        parallaxScale = Math.max(scaleX, scaleY);
        int startX = (int) ((pixelMapSize.width - getWidth() / parallaxScale) / 2);
        int startY = (int) ((pixelMapSize.height - getHeight() / parallaxScale) / 2);
        int drawWidth = (int) (getWidth() / parallaxScale);
        int drawHeight = (int) (getHeight() / parallaxScale);
        if (mMatrix.getTranslateY() > startY * parallaxScale) {
            mMatrix.setTranslateY(startY * parallaxScale);
        } else if (mMatrix.getTranslateY() < -startY * parallaxScale) {
            mMatrix.setTranslateY(-startY * parallaxScale);
        }
        float drawX = 0;
        float drawY = 0;
        int pixmapCreatWidth = getWidth();
        int pixmapCreatHeight = getHeight();
        if (mMatrix.getTranslateX() != 0 || mMatrix.getTranslateY() != 0) {
            float startXTranslateX = mMatrix.getTranslateX() / parallaxScale;
            float startXTranslateY = mMatrix.getTranslateY() / parallaxScale;
            startX -= startXTranslateX;
            startY -= startXTranslateY;
        }
        if (startX < 0) {
            drawWidth = pixelMapSize.width;
            pixmapCreatWidth = (int) (drawWidth * parallaxScale);
            startX = 0;
        }
        if (startY < 0) {
            drawHeight = pixelMapSize.height;
            pixmapCreatHeight = (int) (drawHeight * parallaxScale);
            startY = 0;
        }
        if (drawX > 0) {
            pixmapCreatWidth = (int) (getWidth() - drawX);
            drawWidth = (int) (pixmapCreatWidth / parallaxScale);
        } else {
            if (startX * parallaxScale + getWidth() > pixelMapSize.width * parallaxScale) {
                Log.i("MCropImageView.getDrawPixelmapInfo([]):449   " + (startX * parallaxScale + getWidth()));
                drawWidth = pixelMapSize.width - startX;
                pixmapCreatWidth = (int) (drawWidth * parallaxScale);
            } else {
                pixmapCreatWidth = getWidth();
                drawWidth = (int) (pixmapCreatWidth / parallaxScale);
            }
        }
        if (drawY > 0) {
            pixmapCreatHeight = (int) (getHeight() - drawY);
            drawHeight = (int) (pixmapCreatHeight / parallaxScale);
        } else {
            if (startY * parallaxScale + getHeight() > pixelMapSize.height * parallaxScale) {
                drawHeight = pixelMapSize.height - startY;
                pixmapCreatHeight = (int) (drawHeight * parallaxScale);
            } else {
                pixmapCreatHeight = getHeight();
                drawHeight = (int) (pixmapCreatHeight / parallaxScale);
            }
        }
        return new float[]{Float.valueOf(startX) + 75, Float.valueOf(startY) + 25, Float.valueOf(drawWidth) / (1 + mParallaxRate), Float.valueOf(drawHeight) / (1 + mParallaxRate), Float.valueOf(pixmapCreatWidth), Float.valueOf(pixmapCreatHeight), drawX, drawY};
    }

    @Override
    public void setPixelMap(PixelMap pixelMap) {
        if (pixelMap != null) {
            this.pixelMap = pixelMap;
        }
        super.setPixelMap(pixelMap);
    }


    @Override
    public PixelMap getPixelMap() {
        return pixelMap;
    }

}
